package git.soulbgm.utils;

import java.nio.charset.StandardCharsets;
import java.util.Random;

/**
 * 字符串处理工具类
 *
 * @author SoulBGM
 * @date 2018-4-24
 */
public class StringUtil {

    /**
     * 判断1个或多个字符串是否不为空
     * 判断条件 null 和 长度不为0
     *
     * @param str
     * @return
     */
    public static boolean isNotEmpty(String... str) {
        for (String s : str) {
            if (s == null) {
                return false;
            }
            if (s.trim().length() == 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断1个或多个字符串是否不为空
     * 判断条件 null 和 长度不为0
     *
     * @param str
     * @return
     */
    public static boolean isEmpty(String... str) {
        for (String s : str) {
            if (s == null) {
                return true;
            }
            if (s.trim().length() == 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断1个或多个字符串数组是否不为空
     * 判断条件 null 和 长度不为0
     *
     * @param objects
     * @return
     */
    public static boolean isNotEmptyArray(Object[]... objects) {
        for (Object[] obj : objects) {
            if (obj == null) {
                return false;
            }
            if (obj.length == 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * 源字符串是否包含给定的字符串
     *
     * @param sourceString
     * @param includeString
     * @return
     */
    public static boolean isInclude(String sourceString, String includeString) {
        if (StringUtil.isEmpty(sourceString)) {
            return false;
        }
        if (sourceString.indexOf(includeString) != -1) {
            return true;
        }
        return false;
    }

    /**
     * 判断字符串是否是数字
     *
     * @param cs cs
     * @return boolean
     */
    public static boolean isNumeric(final CharSequence cs) {
        // 判断是否为空，如果为空则返回false
        if (cs == null || cs.length() == 0) {
            return false;
        }
        // 通过 length() 方法计算cs传入进来的字符串的长度，并将字符串长度存放到sz中
        final int sz = cs.length();
        // 通过字符串长度循环
        for (int i = 0; i < sz; i++) {
            // 判断每一个字符是否为数字，如果其中有一个字符不满足，则返回false
            if (!Character.isDigit(cs.charAt(i))) {
                return false;
            }
        }
        // 验证全部通过则返回true
        return true;
    }

    /**
     * 将一组字符才以指定的字符链接起来
     *
     * @param linkStr 链接字符
     * @param strs    需要连接的动态参数
     * @return
     */
    public static String join(String linkStr, Object... strs) {
        if (strs != null && linkStr != null) {
            StringBuilder result = new StringBuilder();
            for (Object temp : strs) {
                result.append(objToStr(temp));
                result.append(linkStr);
            }
            return result.substring(0, result.length() - linkStr.length());
        }
        return null;
    }

    public static String join(String linkStr, byte[] data) {
        if (data != null && linkStr != null) {
            StringBuilder result = new StringBuilder();
            for (byte temp : data) {
                result.append(objToStr(temp)).append(linkStr);
            }
            return result.substring(0, result.length() - linkStr.length());
        }
        return null;
    }

    /**
     * byte[]转String
     *
     * @param bytes
     * @return
     */
    public static String byteArrayToString(byte[] bytes) {
        try {
            return new String(bytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            //e.printStackTrace();
        }
        return null;
    }

    /**
     * Object 转 String
     *
     * @param obj
     * @return
     */
    public static String objToStr(Object obj) {
        String str = String.valueOf(obj);
        return "null".equals(str) ? null : str;
    }

    /**
     * Object 转 String
     * 如果obj为null 则返回 defaultStr 否则 返回转成功后的obj字符串
     *
     * @param obj
     * @return
     */
    public static String objToStr(Object obj, String defaultStr) {
        String str = objToStr(obj);
        return str == null ? defaultStr : str;
    }

    /**
     * 删除起始字符
     *
     * @param str
     * @param trim
     * @return
     */
    public static String trimStart(String str, String trim) {
        if (str == null) {
            return null;
        }
        return str.replaceAll("^(" + trim + ")+", "");
    }

    /**
     * 删除末尾字符
     *
     * @param str
     * @param trim
     * @return
     */
    public static String trimEnd(String str, String trim) {
        if (str == null) {
            return null;
        }
        return str.replaceAll("(" + trim + ")+$", "");
    }

    /**
     * 删除起始和末尾字符
     *
     * @param str
     * @param trim
     * @return
     */
    public static String trimStartEnd(String str, String trim) {
        str = trimStart(str, trim);
        str = trimEnd(str, trim);
        return str;
    }

    /**
     * 由Random生成随机数
     */
    private static Random RANDOM;

    static {
        RANDOM = new Random();
    }

    /**
     * 随机生成一定长度的字符串
     *
     * @param length
     * @return
     */
    public static String getRandomString(int length) {
        //定义一个字符串（A-Z，a-z，0-9）即62位；
        String str = "zxcvbnmlkjhgfdsaqwertyuiopQWERTYUIOPASDFGHJKLZXCVBNM1234567890";
        StringBuilder sb = new StringBuilder();
        //长度为几就循环几次
        for (int i = 0; i < length; ++i) {
            //产生0-61的数字
            int number = RANDOM.nextInt(62);
            //将产生的数字通过length次承载到sb中
            sb.append(str.charAt(number));
        }
        //将承载的字符转换成字符串
        return sb.toString();
    }

    /**
     * 随机生成长度为30的字符串
     *
     * @return
     */
    public static String getRandomString() {
        return getRandomString(30);
    }

    /**
     * 根据给定的字符截取给定字符后面的字符串
     * 从后往前搜索给定字符
     * 例子：cutOutEndString("123.txt", ".", false);   结果：txt
     * 例子：cutOutEndString("123.txt", ".", true);   结果：.txt
     *
     * @param source
     * @param cutOutSymbol
     * @param last         true从末尾处开始查找给定字符串    false从开始处开始查找给定字符串
     * @param flag         true包含给定字符串   false不包含
     * @return
     */
    public static String cutOutEndString(String source, String cutOutSymbol, boolean last, boolean flag) {
        if (isEmpty(source, cutOutSymbol)) {
            return null;
        }
        int increment = cutOutSymbol.length();
        if (flag) {
            increment = 0;
        }
        String str = null;
        int index;
        if (last) {
            index = source.lastIndexOf(cutOutSymbol);
        } else {
            index = source.indexOf(cutOutSymbol);
        }
        if (index != -1) {
            str = source.substring(index + increment, source.length());
        }
        return str;
    }

    /**
     * 根据给定的字符截取给定字符后面的字符串
     * 从后往前搜索给定字符
     * 例子：cutOutEndString("123.txt", ".");   结果：txt
     *
     * @param source
     * @param cutOutSymbol
     * @param last         true从末尾处开始查找给定字符串    false从开始处开始查找给定字符串
     * @return
     */
    public static String cutOutEndString(String source, String cutOutSymbol, boolean last) {
        return cutOutEndString(source, cutOutSymbol, last, false);
    }

    /**
     * 根据给定的字符截取给定字符前面的字符串
     * 从后往前搜索给定字符
     * 例子：cutOutEndString("123.txt", ".", false);   结果：123
     * 例子：cutOutEndString("123.txt", ".", true);   结果：123.
     *
     * @param source
     * @param cutOutSymbol
     * @param last         true从末尾处开始查找给定字符串    false从开始处开始查找给定字符串
     * @param flag         true包含给定字符串 false不包含
     * @return
     */
    public static String cutOutTopString(String source, String cutOutSymbol, boolean last, boolean flag) {
        if (isEmpty(source, cutOutSymbol)) {
            return null;
        }
        int increment = 0;
        if (flag) {
            increment = cutOutSymbol.length();
        }
        String str = null;
        int index;
        if (last) {
            index = source.lastIndexOf(cutOutSymbol);
        } else {
            index = source.indexOf(cutOutSymbol);
        }
        if (index != -1) {
            str = source.substring(0, index + increment);
        }
        return str;
    }

    /**
     * 根据给定的字符截取给定字符前面的字符串
     * 从后往前搜索给定字符
     * 例子：cutOutEndString("123.txt", ".");   结果：123
     *
     * @param source
     * @param cutOutSymbol
     * @param last         true从末尾处开始查找给定字符串    false从开始处开始查找给定字符串
     * @return
     */
    public static String cutOutTopString(String source, String cutOutSymbol, boolean last) {
        return cutOutTopString(source, cutOutSymbol, last, false);
    }

    /**
     * 转换${start}开始${end}结束(不包括${end}位置)的字符串为小写
     *
     * @param str
     * @param start
     * @param end
     * @return
     */
    public static String toLowerCase(String str, int start, int end) {
        if (isEmpty(str)) {
            return null;
        }
        String str2 = str.substring(start, end);
        str2 = str2.toLowerCase();
        if (end < str.length()) {
            str = str.substring(0, start) + str2 + str.substring(end);
        } else {
            str = str2;
        }
        return str;
    }

    /**
     * 转换字符串为小写
     *
     * @param str
     * @return
     */
    public static String toLowerCase(String str) {
        if (isEmpty(str)) {
            return null;
        }
        return str.toLowerCase();
    }

    /**
     * 转换${start}开始${end}结束(不包括${end}位置)的字符串为大写
     *
     * @param str
     * @param start
     * @param end
     * @return
     */
    public static String toUpperCase(String str, int start, int end) {
        if (isEmpty(str)) {
            return null;
        }
        String str2 = str.substring(start, end);
        str2 = str2.toUpperCase();
        if (end < str.length()) {
            str = str.substring(0, start) + str2 + str.substring(end);
        } else {
            str = str2;
        }
        return str;
    }

    /**
     * 转换字符串为大写
     *
     * @param str
     * @return
     */
    public static String toUpperCase(String str) {
        if (isEmpty(str)) {
            return null;
        }
        return str.toUpperCase();
    }

    private static final String UNICODE = "\\u";

    /**
     * 中文转Unicode
     *
     * @param gbString
     * @return
     */
    public static String gbEncoding(final String gbString) {
        char[] utfBytes = gbString.toCharArray();
        StringBuilder unicodeBytes = new StringBuilder("");
        for (int byteIndex = 0; byteIndex < utfBytes.length; byteIndex++) {
            //转换为16进制整型字符串
            String hexB = Integer.toHexString(utfBytes[byteIndex]);
            if (hexB.length() <= 2) {
                hexB = "00" + hexB;
            }
            unicodeBytes.append(UNICODE).append(hexB);
        }
        return unicodeBytes.toString();
    }

    /**
     * Unicode转中文
     *
     * @param dataStr
     * @return
     */
    public static String decodeUnicode(final String dataStr) {
        int start = 0;
        int end;
        final StringBuffer buffer = new StringBuffer();
        while (start > -1) {
            end = dataStr.indexOf(UNICODE, start + 2);
            String charStr;
            if (end == -1) {
                charStr = dataStr.substring(start + 2, dataStr.length());
            } else {
                charStr = dataStr.substring(start + 2, end);
            }
            // 16进制parse整形字符串。
            char letter = (char) Integer.parseInt(charStr, 16);
            if (letter != 0) {
                buffer.append(Character.toString(letter));
            }
            start = end;
        }
        return buffer.toString();
    }

    /**
     * 拆分字符串
     *
     * @param source
     * @param regex
     * @return
     */
    public static String[] split(String source, String regex) {
        if (source == null || regex == null) {
            return null;
        }
        return source.split(regex);
    }

    /**
     * 使用站位符拼接字符串
     * 格式：sdsdf{}jsk{}sss{}
     *
     * @param format   有占位符的字符串
     * @param argArray 占位符上具体的值
     * @return 拼接之后的字符串
     */
    public static String format(String format, Object... argArray) {
        if (format == null || argArray == null) {
            return "";
        }
        StringBuilder sbuf = new StringBuilder(format.length() + 50);
        int index = 0;
        for (int i = 0; i < argArray.length; i++) {
            int j = format.indexOf("{}", index);
            if (j == -1) {
                sbuf.append(format, index, format.length());
                ArrayFormatCommon.deeplyAppendParameter(sbuf, argArray[i]);
                return sbuf.toString();
            } else {
                sbuf.append(format, index, j);
                ArrayFormatCommon.deeplyAppendParameter(sbuf, argArray[i]);
                index = j + 2;
            }
        }
        sbuf.append(format, index, format.length());
        return sbuf.toString();
    }

    static class ArrayFormatCommon {
        private static void deeplyAppendParameter(StringBuilder sbuf, Object o) {
            if (o == null) {
                sbuf.append("null");
            } else {
                if (!o.getClass().isArray()) {
                    sbuf.append(o.toString());
                } else if (o instanceof boolean[]) {
                    booleanArrayAppend(sbuf, (boolean[]) o);
                } else if (o instanceof byte[]) {
                    byteArrayAppend(sbuf, (byte[]) o);
                } else if (o instanceof char[]) {
                    charArrayAppend(sbuf, (char[]) o);
                } else if (o instanceof short[]) {
                    shortArrayAppend(sbuf, (short[]) o);
                } else if (o instanceof int[]) {
                    intArrayAppend(sbuf, (int[]) o);
                } else if (o instanceof long[]) {
                    longArrayAppend(sbuf, (long[]) o);
                } else if (o instanceof float[]) {
                    floatArrayAppend(sbuf, (float[]) o);
                } else if (o instanceof double[]) {
                    doubleArrayAppend(sbuf, (double[]) o);
                } else if (o instanceof String[]) {
                    stringArrayAppend(sbuf, (String[]) o);
                }
            }
        }

        static boolean isEscapedDelimeter(String messagePattern, int delimeterStartIndex) {
            if (delimeterStartIndex == 0) {
                return false;
            } else {
                char potentialEscape = messagePattern.charAt(delimeterStartIndex - 1);
                return potentialEscape == '\\';
            }
        }

        private static void booleanArrayAppend(StringBuilder sbuf, boolean[] a) {
            sbuf.append('[');
            int len = a.length;

            for (int i = 0; i < len; ++i) {
                sbuf.append(a[i]);
                if (i != len - 1) {
                    sbuf.append(", ");
                }
            }

            sbuf.append(']');
        }

        private static void byteArrayAppend(StringBuilder sbuf, byte[] a) {
            sbuf.append('[');
            int len = a.length;

            for (int i = 0; i < len; ++i) {
                sbuf.append(a[i]);
                if (i != len - 1) {
                    sbuf.append(", ");
                }
            }

            sbuf.append(']');
        }

        private static void charArrayAppend(StringBuilder sbuf, char[] a) {
            sbuf.append('[');
            int len = a.length;

            for (int i = 0; i < len; ++i) {
                sbuf.append(a[i]);
                if (i != len - 1) {
                    sbuf.append(", ");
                }
            }

            sbuf.append(']');
        }

        private static void shortArrayAppend(StringBuilder sbuf, short[] a) {
            sbuf.append('[');
            int len = a.length;

            for (int i = 0; i < len; ++i) {
                sbuf.append(a[i]);
                if (i != len - 1) {
                    sbuf.append(", ");
                }
            }

            sbuf.append(']');
        }

        private static void intArrayAppend(StringBuilder sbuf, int[] a) {
            sbuf.append('[');
            int len = a.length;

            for (int i = 0; i < len; ++i) {
                sbuf.append(a[i]);
                if (i != len - 1) {
                    sbuf.append(", ");
                }
            }

            sbuf.append(']');
        }

        private static void longArrayAppend(StringBuilder sbuf, long[] a) {
            sbuf.append('[');
            int len = a.length;

            for (int i = 0; i < len; ++i) {
                sbuf.append(a[i]);
                if (i != len - 1) {
                    sbuf.append(", ");
                }
            }

            sbuf.append(']');
        }

        private static void floatArrayAppend(StringBuilder sbuf, float[] a) {
            sbuf.append('[');
            int len = a.length;

            for (int i = 0; i < len; ++i) {
                sbuf.append(a[i]);
                if (i != len - 1) {
                    sbuf.append(", ");
                }
            }

            sbuf.append(']');
        }

        private static void doubleArrayAppend(StringBuilder sbuf, double[] a) {
            sbuf.append('[');
            int len = a.length;

            for (int i = 0; i < len; ++i) {
                sbuf.append(a[i]);
                if (i != len - 1) {
                    sbuf.append(", ");
                }
            }

            sbuf.append(']');
        }

        private static void stringArrayAppend(StringBuilder sbuf, String[] a) {
            sbuf.append('[');
            int len = a.length;

            for (int i = 0; i < len; ++i) {
                sbuf.append(a[i]);
                if (i != len - 1) {
                    sbuf.append(", ");
                }
            }

            sbuf.append(']');
        }

    }

    /**
     * @Method: appendHead
     * @Description: 字符串  拼接指定长度的0，或低位截取指定长度
     * @Param []
     * @Return java.lang.String
     * @Author : songchunli
     * @CreateDate : 2018/8/7 17:43
     */
    public static String appendHead(int len, String str, boolean flag) {
        //整数拼接指定的0，负数低位截取指定长度
        StringBuffer buffer = new StringBuffer();
        if (flag) {
            for (int i = 0; i < len; i++) {
                buffer.append("0");
            }
            buffer.append(str);
            str = buffer.toString();
        } else {
            str = str.substring(str.length() - len, str.length());
        }
        return str;
    }

}
